package de.bazinga.rotw.menu;

import java.util.Hashtable;
import java.util.Iterator;

import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.InputHandler;
import com.jme.input.MouseInput;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.game.state.BasicGameState;
import com.jmex.game.state.GameState;

import de.bazinga.rotw.game.Game;
import de.bazinga.rotw.menu.item.MenuItem;
import de.bazinga.rotw.menu.item.TextItem;
import de.bazinga.rotw.sound.Sound;

public class Menu extends BasicGameState {
	
	
	private AbsoluteMouse am = null;
	
	private InputHandler input = new InputHandler();
	
	protected Hashtable<String,MenuItem> menuItems = new Hashtable<String,MenuItem>();
	protected Hashtable<String,MenuItem> otherItems = new Hashtable<String,MenuItem>();
	protected Hashtable<String,TextItem> textItems = new Hashtable<String,TextItem>();
	
	/**
	 * Saves the last time the Click-Sound was played
	 */
	protected long lastPlayerSound = 0;
	

	// Save lastClickTime so we dont take think the player clicked x times
	protected long lastClick = 0;

	public Menu(String name) {
		super(name);

		init();
		
		initCamera();
		initMouse();
		
		initMenuItems();
		

        // Finish up
		getRootNode().updateRenderState();
		getRootNode().updateWorldBound();
		getRootNode().updateGeometricState(0.0f, true);
	}
	
	
	protected void init() {
		// Overwrite
	}
	
	
	protected void initMenuItems() {
		// Overwrite
	}
	
	
	
	private void initMouse() {
		am = new AbsoluteMouse("Mouse",
				Game.getGame().getDisplay().getWidth(),
				Game.getGame().getDisplay().getHeight());
		
		
		TextureState cursor = Game.getGame().getDisplay().getRenderer().createTextureState();
        cursor.setEnabled(true);
        cursor.setTexture(TextureManager.loadTexture(Menu.class
                .getClassLoader().getResource("cursor/cursor.png"),
                Texture.MinificationFilter.BilinearNearestMipMap,
                Texture.MagnificationFilter.Bilinear));
        am.setRenderState(cursor);
		
		BlendState bs = Game.getGame().getDisplay().getRenderer().createBlendState();
		bs.setBlendEnabled(true);
		bs.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
		bs.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
		bs.setTestEnabled(true);
		bs.setTestFunction(BlendState.TestFunction.GreaterThan);
		
		am.setRenderState(bs);
		
		// Get the mouse input device and assign it to the AbsoluteMouse
        // Move the mouse to the middle of the screen to start with
        am.setLocalTranslation(
        		new Vector3f(
        				Game.getGame().getDisplay().getWidth() / 2, 
        				Game.getGame().getDisplay().getHeight() / 2, 
        				0)
        		);
        // Assign the mouse to an input handler
        am.registerWithInputHandler( input );
 
        
        am.updateRenderState();
		
		getRootNode().attachChild(am);
	}
	
	public void initCamera() {
		Game.getGame().getCamera().setLocation(new Vector3f(0,0,10));
		
		Game.getGame().getCamera().lookAt(new Vector3f( 0f, 0f, -1 ),Vector3f.UNIT_Y);
	}
	
	
	
	public void setActive(boolean status) {
		if(status) {
			lastClick = System.currentTimeMillis();
			initCamera();
		}
		super.setActive(status);
	}
	
	
	
	protected void handleClick(String item) {
		// Overwrite
	}
	
	protected void handleHover(MenuItem item) {
		// Overwrite
	}
	
	
	/**
	 * Updates the rootNode.
	 * 
	 * @see GameState#update(float)
	 */
	public void update(float tpf) {
		super.update(tpf);
		
		if(!this.isActive()) return ;

		
		Vector2f mousePos = new Vector2f(
				am.getHotSpotPosition().x ,
				am.getHotSpotPosition().y );
		
		for(TextItem ti:textItems.values()) {
			ti.update();
			
			if(mousePos.x > ti.getX() &&
					mousePos.y > ti.getY() &&
					mousePos.x < (ti.getX() + ti.getWidth()) &&
					mousePos.y < (ti.getY() + ti.getHeight()) &&
					MouseInput.get().isButtonDown(0)) {
				// hit
				ti.setActive(true);
				// Play Sound
				playSound();
			}
		}

		// only accept a click every 100 ms
		if((System.currentTimeMillis() - lastClick) > 200) {
		
			Iterator<MenuItem> it = menuItems.values().iterator();
			while(it.hasNext()) {
				MenuItem item = it.next();
				if(!item.isImage()) {
					if(mousePos.x > item.getX() &&
							mousePos.y > item.getY() &&
							mousePos.x < (item.getX() + item.getWidth()) &&
							mousePos.y < (item.getY() + item.getHeight())) {
						// hit
						if(MouseInput.get().isButtonDown(0)) {
							for(TextItem ti:textItems.values()) ti.setActive(false);
							
							handleClick(item.getName());
							
							// Play Sound
							playSound();
							
							lastClick = System.currentTimeMillis();
							
						}else{
							handleHover(item);
						}
						item.setActive(true);
					}else{
						item.setActive(false);
					}
				}else if(mousePos.x > (item.getX() - (item.getWidth()/2.0f)) &&
							mousePos.y > (item.getY() - (item.getHeight()/2.0f)) &&
							mousePos.x < (item.getX() + (item.getWidth()/2.0f)) &&
							mousePos.y < (item.getY() + (item.getHeight()/2.0f))) {
					// hit
					if(MouseInput.get().isButtonDown(0)) {
						for(TextItem ti:textItems.values()) ti.setActive(false);
						
						handleClick(item.getName());
						
						// Play Sound
						playSound();
						
						lastClick = System.currentTimeMillis();
						
					}else{
						handleHover(item);
					}
					item.setActive(true);
				}else{
					item.setActive(false);
				}
			}
		}
		
		input.update(tpf);
	}

	/**
	 * Draws the rootNode.
	 * 
	 * @see GameState#render(float)
	 */
	public void render(float tpf) {
		super.render(tpf);
		
		Iterator<MenuItem> it = menuItems.values().iterator();
		while(it.hasNext()) {			
			DisplaySystem.getDisplaySystem().getRenderer().draw(it.next());
		}

		it = otherItems.values().iterator();
		while(it.hasNext()) {			
			DisplaySystem.getDisplaySystem().getRenderer().draw(it.next());
		}
		
		Iterator<TextItem> i = textItems.values().iterator();
		while(i.hasNext()) {	
			DisplaySystem.getDisplaySystem().getRenderer().draw(i.next());
		}
	}
	
	
	
	
	protected void playSound() {
		if(!Game.getGame().getSettings().isSFX()) return ;
		
		if( ( System.currentTimeMillis() - lastPlayerSound) > 200) {
			Sound.getInstance().getAudioTrack("sounds/button.wav").play();
			lastPlayerSound = System.currentTimeMillis();
		}
	}
}
